#pragma once
 
#include "qcontrol.h"
 


namespace micro{
namespace gui 
{
 
//enum    iStyles  { LVS_ICON, LVS_SMALLICON, LVS_LIST, LVS_REPORT };


/*

class QListControl2: public QControl
{
public:
  bool Create(QWindow * parent, int id, UINT style=LVS_LIST);
 
  bool CreateEx(DWORD exStyle, DWORD style,
      int x, int y, int width, int height,
      HWND parentWindow, HMENU idOrHMenu, 
      HINSTANCE instance, LPVOID createParam);

  bool SetBkColor(QCOLOR color)
    { return toBool( ListView_SetBkColor(_window,color)  ); }
 
  QCOLOR GetBkColor( )
    { return  ListView_GetBkColor(_window ); }

  bool SetTextBkColor(QCOLOR color)
    { return toBool( ListView_SetTextBkColor(_window,color)  ); }
 
  QCOLOR GetTextBkColor( )
    { return  ListView_GetTextBkColor(_window ); }


   
 

  bool SetUnicodeFormat(bool fUnicode)
    { return toBool(ListView_SetUnicodeFormat(_window, toBool(fUnicode))); }
 
  bool DeleteAllItems()
    { return toBool(ListView_DeleteAllItems(_window)); }


  int InsertColumn(int columnIndex, const LVCOLUMN *columnInfo)
    { return ListView_InsertColumn(_window, columnIndex, columnInfo); }
  
  bool DeleteColumn(int columnIndex)
    { return toBool(ListView_DeleteColumn(_window, columnIndex)); }

  int InsertItem(const LVITEM* item)
    { return ListView_InsertItem(_window, item); }
  

  bool SetItem(const LVITEM* item)
    { return toBool(ListView_SetItem(_window, item)); }
   

  bool DeleteItem(int itemIndex)
    { return toBool(ListView_DeleteItem(_window, itemIndex)); }

  UINT GetSelectedCount() const
    { return ListView_GetSelectedCount(_window); }
  int GetItemCount() const
    { return ListView_GetItemCount(_window); }

  INT GetSelectionMark() const
    { return ListView_GetSelectionMark(_window); }

  void SetItemCount(int numItems)
    {  ListView_SetItemCount(_window, numItems); }
  void SetItemCountEx(int numItems, DWORD flags)
    {  ListView_SetItemCountEx(_window, numItems, flags); }

  int GetNextItem(int startIndex, UINT flags) const
    { return ListView_GetNextItem(_window, startIndex, flags); }

  int GetNextSelectedItem(int startIndex) const
    { return GetNextItem(startIndex, LVNI_SELECTED); }

  int GetFocusedItem() const
    { return GetNextItem(-1, LVNI_FOCUSED); }
  
  bool GetItem(LVITEM* item) const 
    { return toBool(ListView_GetItem(_window, item)); }

  bool GetItemParam(int itemIndex, LPARAM &param) const ;

  void SetItemText(int itemIndex, int aSubItemIndex, LPTSTR aText) const 
    { ListView_SetItemText(_window, itemIndex, aSubItemIndex, aText); }

    void GetItemText(int itemIndex, int aSubItemIndex, LPTSTR aText, int aTextSizeMax) const 
    { ListView_GetItemText(_window, itemIndex, aSubItemIndex, aText, aTextSizeMax); }

  bool SortItems(PFNLVCOMPARE compareFunction, LPARAM dataParam)
    { return toBool(ListView_SortItems(_window, compareFunction, dataParam)); }

  void SetItemState(int index, UINT state, UINT mask)
    { ListView_SetItemState(_window, index, state, mask); }

  UINT GetItemState(int index, UINT mask) const
    { return ListView_GetItemState(_window, index, mask); }

  bool GetColumn(int columnIndex, LVCOLUMN* columnInfo) const
    { return toBool(ListView_GetColumn(_window, columnIndex, columnInfo)); }

  HIMAGELIST SetImageList(HIMAGELIST imageList, int imageListType)
    { return ListView_SetImageList(_window, imageList, imageListType); }		

  HIMAGELIST GetImageList(int imageListType)
    { return ListView_GetImageList(_window, imageListType); }		


  // version 4.70: NT5 | (NT4 + ie3) | w98 | (w95 + ie3)
  DWORD GetExtendedListViewStyle()
    { return ListView_GetExtendedListViewStyle(_window); }

  void SetExtendedListViewStyle(DWORD exStyle)
    { ListView_SetExtendedListViewStyle(_window, exStyle); }

  void SetExtendedListViewStyle(DWORD exMask, DWORD exStyle)
    { ListView_SetExtendedListViewStyleEx(_window, exMask, exStyle); }

   
  void SetCheckState(UINT index, bool checkState)
    { ListView_SetCheckState(_window, index, toBOOL(checkState)); }
  
  bool GetCheckState(UINT index)
    { return toBool(ListView_GetCheckState(_window, index)); }


  bool EnsureVisible(int index, bool partialOK)
    { return toBool(ListView_EnsureVisible(_window, index, toBOOL(partialOK))); }

  bool GetItemRect(int index, RECT *rect, int code)
    { return toBool(ListView_GetItemRect(_window, index, rect, code)); }

  HWND GetEditControl()
    { return ListView_GetEditControl(_window) ; }
  HWND EditLabel(int itemIndex)
    { return ListView_EditLabel(_window, itemIndex) ; }

  bool RedrawItems(int firstIndex, int lastIndex)
    { return toBool(ListView_RedrawItems(_window, firstIndex, lastIndex)); }

  bool RedrawAllItems()
  { 
    if (GetItemCount() > 0)
      return RedrawItems(0, GetItemCount() - 1);
    return true;
  }

  bool RedrawItem(int index)
    { return RedrawItems(index, index); }
 
  int HitTest(LPLVHITTESTINFO info)
    { return ListView_HitTest(_window, info); }


  HWND GetHeader()
  {
	  return ListView_GetHeader(_window);
  }







protected:
	// Overidables.
	virtual LRESULT OnBeginDrag( LPNMLISTVIEW pListView, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnBeginLabelEdit( NMLVDISPINFO *pDispInfo, BOOL& bNotifyParent )
	{ return FALSE; }

	virtual LRESULT OnBeginRDrag( LPNMLISTVIEW pListView, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnColumnClick( LPNMLISTVIEW pListView, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnDeleteAllItems( LPNMLISTVIEW pListView, BOOL& bNotifyParent )
	{ return FALSE; }

	virtual LRESULT OnDeleteItem( LPNMLISTVIEW pListView, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnEndLabelEdit( NMLVDISPINFO *pDispInfo, BOOL& bNotifyParent )
	{ return TRUE; }

	virtual LRESULT OnGetDispInfo( NMLVDISPINFO *pDispInfo, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnGetInfoTip( LPNMLVGETINFOTIP pGetInfoTip, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnInsertItem( LPNMLISTVIEW pListView, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnHotTrack( LPNMLISTVIEW pListView, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnItemActivate( LPNMITEMACTIVATE pItemActive, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnItemChanged( LPNMLISTVIEW pListView, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnItemChanging( LPNMLISTVIEW pListView, BOOL& bNotifyParent )
	{ return FALSE; }

	virtual LRESULT OnKeyDown( LPNMLVKEYDOWN pKeyDown, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnMarqueeBegin( LPNMLISTVIEW pListView, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnODCachehint( NMLVCACHEHINT *pCachehint, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnODFindItem( LPNMLVFINDITEM pFindItem, BOOL& bNotifyParent )
	{ return -1; }

	virtual LRESULT OnODStateChanged( LPNMLVODSTATECHANGE pStateChange, BOOL& bNotifyParent )
	{ return 0; }

	virtual LRESULT OnSetDispInfo( NMLVDISPINFO *pDispInfo, BOOL& bNotifyParent )
	{ return FALSE; }

	// Reflected notification handler which will call
	// the virtual notification handlers.
	virtual LRESULT OnReflectedNotify( LPNMHDR pNMHDR, BOOL& bNotifyParent )
	{
		// Evaluate notification code.
		switch ( pNMHDR->code )
		{
			case	LVN_BEGINDRAG:      return OnBeginDrag(( LPNMLISTVIEW )pNMHDR, bNotifyParent );
			case	LVN_BEGINLABELEDIT: return OnBeginLabelEdit(( NMLVDISPINFO * )pNMHDR, bNotifyParent );
			case	LVN_BEGINRDRAG:     return OnBeginRDrag(( LPNMLISTVIEW )pNMHDR, bNotifyParent );
			case	LVN_COLUMNCLICK:    return OnColumnClick(( LPNMLISTVIEW )pNMHDR, bNotifyParent );
			case	LVN_DELETEALLITEMS: return OnDeleteAllItems(( LPNMLISTVIEW )pNMHDR, bNotifyParent );
			case	LVN_DELETEITEM:     return OnDeleteItem(( LPNMLISTVIEW )pNMHDR, bNotifyParent );
			case	LVN_ENDLABELEDIT:   return OnEndLabelEdit(( NMLVDISPINFO * )pNMHDR, bNotifyParent );
			case	LVN_GETDISPINFO:    return OnGetDispInfo(( NMLVDISPINFO * )pNMHDR, bNotifyParent );
			case	LVN_GETINFOTIP:     return OnGetInfoTip(( LPNMLVGETINFOTIP )pNMHDR, bNotifyParent );
			case	LVN_HOTTRACK:	    return OnHotTrack(( LPNMLISTVIEW )pNMHDR, bNotifyParent );
			case	LVN_INSERTITEM:	    return OnInsertItem(( LPNMLISTVIEW )pNMHDR, bNotifyParent );
			case	LVN_ITEMACTIVATE:   return OnItemActivate(( LPNMITEMACTIVATE )pNMHDR, bNotifyParent );
			case	LVN_ITEMCHANGED:    return OnItemChanged(( LPNMLISTVIEW )pNMHDR, bNotifyParent );
			case	LVN_ITEMCHANGING:   return OnItemChanging(( LPNMLISTVIEW )pNMHDR, bNotifyParent );
			case	LVN_KEYDOWN:	    return OnKeyDown(( LPNMLVKEYDOWN )pNMHDR, bNotifyParent );
			case	LVN_MARQUEEBEGIN:   return OnMarqueeBegin(( LPNMLISTVIEW )pNMHDR, bNotifyParent );
			case	LVN_ODCACHEHINT:    return OnODCachehint(( NMLVCACHEHINT * )pNMHDR, bNotifyParent );
			case	LVN_ODFINDITEM:	    return OnODFindItem(( LPNMLVFINDITEM )pNMHDR, bNotifyParent );
			case	LVN_ODSTATECHANGED: return OnODStateChanged(( LPNMLVODSTATECHANGE )pNMHDR, bNotifyParent );
			case	LVN_SETDISPINFO:    return OnSetDispInfo(( NMLVDISPINFO * )pNMHDR, bNotifyParent );
		}
		// Call the base class.
		return QControl::OnReflectedNotify( pNMHDR, bNotifyParent );
	}
   
};
*/









 
class QListCtrl : public QControl
{
public:
// Constructors
	QListCtrl(HWND hWnd = nullptr) : QControl(hWnd)
	{ }

	QListCtrl& operator =(HWND hWnd)
	{
		_window = hWnd;
		return *this;
	}

	bool Create(QWindow * parent, int id = 0, UINT style=LVS_LIST);
 
  
// Attributes
	virtual LPCTSTR GetWndClassName()
	{
		return WC_LISTVIEW;
	}

	COLORREF GetBkColor() const
	{
		ASSERT(::IsWindow(_window));
		return (COLORREF)::SendMessage(_window, LVM_GETBKCOLOR, 0, 0L);
	}

	BOOL SetBkColor(COLORREF cr)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETBKCOLOR, 0, cr);
	}

	QImageList GetImageList(int nImageListType) const
	{
		ASSERT(::IsWindow(_window));
		return QImageList((HIMAGELIST)::SendMessage(_window, LVM_GETIMAGELIST, nImageListType, 0L));
	}

	QImageList SetImageList(HIMAGELIST hImageList, int nImageList)
	{
		ASSERT(::IsWindow(_window)); 
		return QImageList((HIMAGELIST)::SendMessage(_window, LVM_SETIMAGELIST, nImageList, (LPARAM)hImageList));
	}

	int GetItemCount() const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETITEMCOUNT, 0, 0L);
	}

	BOOL SetItemCount(int nItems)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETITEMCOUNT, nItems, 0L);
	}

	BOOL GetItem(LPLVITEM pItem) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETITEM, 0, (LPARAM)pItem);
	}

	BOOL SetItem(const LVITEM* pItem)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETITEM, 0, (LPARAM)pItem);
	}

	BOOL SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem,
		int nImage, UINT nState, UINT nStateMask, LPARAM lParam)
	{
		ASSERT(::IsWindow(_window));
		LVITEM lvi = { 0 };
		lvi.mask = nMask;
		lvi.iItem = nItem;
		lvi.iSubItem = nSubItem;
		lvi.stateMask = nStateMask;
		lvi.state = nState;
		lvi.pszText = (LPTSTR) lpszItem;
		lvi.iImage = nImage;
		lvi.lParam = lParam;
		return (BOOL)::SendMessage(_window, LVM_SETITEM, 0, (LPARAM)&lvi);
	}

	UINT GetItemState(int nItem, UINT nMask) const
	{
		ASSERT(::IsWindow(_window));
		return (UINT)::SendMessage(_window, LVM_GETITEMSTATE, nItem, nMask);
	}

	BOOL SetItemState(int nItem, UINT nState, UINT nStateMask)
	{
		ASSERT(::IsWindow(_window));
		LVITEM lvi = { 0 };
		lvi.state = nState;
		lvi.stateMask = nStateMask;
		return (BOOL)::SendMessage(_window, LVM_SETITEMSTATE, nItem, (LPARAM)&lvi);
	}

	BOOL SetItemState(int nItem, LPLVITEM pItem)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETITEMSTATE, nItem, (LPARAM)pItem);
	}

#ifndef _ATL_NO_COM
	BOOL GetItemText(int nItem, int nSubItem, BSTR& bstrText) const
	{
		//USES_CONVERSION;
		ASSERT(::IsWindow(_window));
		ASSERT(bstrText == nullptr);
		LVITEM lvi = { 0 };
		lvi.iSubItem = nSubItem;

		LPTSTR lpstrText = nullptr;
		int nRes = 0;
		for(int nLen = 256; ; nLen *= 2)
		{
			lpstrText = new TCHAR[nLen];
			if(lpstrText == nullptr)
				break;
			lpstrText[0] = 0;
			lvi.cchTextMax = nLen;
			lvi.pszText = lpstrText;
			nRes  = (int)::SendMessage(_window, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
			if(nRes < nLen - 1)
				break;
			delete [] lpstrText;
			lpstrText = nullptr;
		}

		if(lpstrText != nullptr)
		{
			if(nRes != 0)
				bstrText = ::SysAllocString(lpstrText);
			delete [] lpstrText;
		}

		return (bstrText != nullptr) ? TRUE : FALSE;
	}
#endif // !_ATL_NO_COM

#if defined(USE_STRING) 
	int GetItemText(int nItem, int nSubItem, _CSTRING_NS::CString& strText) const
	{
		ASSERT(::IsWindow(_window));
		LVITEM lvi = { 0 };
		lvi.iSubItem = nSubItem;

		strText.Empty();
		int nRes = 0;
		for(int nLen = 256; ; nLen *= 2)
		{
			lvi.cchTextMax = nLen;
			lvi.pszText = strText.GetBufferSetLength(nLen);
			if(lvi.pszText == nullptr)
			{
				nRes = 0;
				break;
			}
			nRes  = (int)::SendMessage(_window, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
			if(nRes < nLen - 1)
				break;
		}
		strText.ReleaseBuffer();
		return nRes;
	}
#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__)

	int GetItemText(int nItem, int nSubItem, LPTSTR lpszText, int nLen) const
	{
		ASSERT(::IsWindow(_window));
		LVITEM lvi = { 0 };
		lvi.iSubItem = nSubItem;
		lvi.cchTextMax = nLen;
		lvi.pszText = lpszText;
		return (int)::SendMessage(_window, LVM_GETITEMTEXT, (WPARAM)nItem, (LPARAM)&lvi);
	}

	BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpszText)
	{
		ASSERT(::IsWindow(_window));
		return SetItem(nItem, nSubItem, LVIF_TEXT, lpszText, 0, 0, 0, 0);
	}

	DWORD_PTR GetItemData(int nItem) const
	{
		ASSERT(::IsWindow(_window));
		LVITEM lvi = { 0 };
		lvi.iItem = nItem;
		lvi.mask = LVIF_PARAM;
		BOOL bRet = (BOOL)::SendMessage(_window, LVM_GETITEM, 0, (LPARAM)&lvi);
		return (DWORD_PTR)(bRet ? lvi.lParam : 0);
	}

	BOOL SetItemData(int nItem, DWORD_PTR dwData)
	{
		ASSERT(::IsWindow(_window));
		return SetItem(nItem, 0, LVIF_PARAM, nullptr, 0, 0, 0, (LPARAM)dwData);
	}

	UINT GetCallbackMask() const
	{
		ASSERT(::IsWindow(_window));
		return (UINT)::SendMessage(_window, LVM_GETCALLBACKMASK, 0, 0L);
	}

	BOOL SetCallbackMask(UINT nMask)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETCALLBACKMASK, nMask, 0L);
	}

	BOOL GetItemPosition(int nItem, LPPOINT lpPoint) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETITEMPOSITION, nItem, (LPARAM)lpPoint);
	}

	BOOL SetItemPosition(int nItem, POINT pt)
	{
		ASSERT(::IsWindow(_window));
		ASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON));
		return (BOOL)::SendMessage(_window, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt);
	}

	BOOL SetItemPosition(int nItem, int x, int y)
	{
		ASSERT(::IsWindow(_window));
		ASSERT(((GetStyle() & LVS_TYPEMASK) == LVS_ICON) || ((GetStyle() & LVS_TYPEMASK) == LVS_SMALLICON));
		POINT pt = { x, y };
		return (BOOL)::SendMessage(_window, LVM_SETITEMPOSITION32, nItem, (LPARAM)&pt);
	}

	int GetStringWidth(LPCTSTR lpsz) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETSTRINGWIDTH, 0, (LPARAM)lpsz);
	}

	QEdit GetEditControl() const
	{
		ASSERT(::IsWindow(_window));
		return QEdit((HWND)::SendMessage(_window, LVM_GETEDITCONTROL, 0, 0L));
	}

	BOOL GetColumn(int nCol, LVCOLUMN* pColumn) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETCOLUMN, nCol, (LPARAM)pColumn);
	}

	BOOL SetColumn(int nCol, const LVCOLUMN* pColumn)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETCOLUMN, nCol, (LPARAM)pColumn);
	}

	int GetColumnWidth(int nCol) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETCOLUMNWIDTH, nCol, 0L);
	}

	BOOL SetColumnWidth(int nCol, int cx)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETCOLUMNWIDTH, nCol, MAKELPARAM(cx, 0));
	}

	BOOL GetViewRect(LPRECT lpRect) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETVIEWRECT, 0, (LPARAM)lpRect);
	}

	COLORREF GetTextColor() const
	{
		ASSERT(::IsWindow(_window));
		return (COLORREF)::SendMessage(_window, LVM_GETTEXTCOLOR, 0, 0L);
	}

	BOOL SetTextColor(COLORREF cr)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETTEXTCOLOR, 0, cr);
	}

	COLORREF GetTextBkColor() const
	{
		ASSERT(::IsWindow(_window));
		return (COLORREF)::SendMessage(_window, LVM_GETTEXTBKCOLOR, 0, 0L);
	}

	BOOL SetTextBkColor(COLORREF cr)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETTEXTBKCOLOR, 0, cr);
	}

	int GetTopIndex() const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETTOPINDEX, 0, 0L);
	}

	int GetCountPerPage() const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETCOUNTPERPAGE, 0, 0L);
	}

	BOOL GetOrigin(LPPOINT lpPoint) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETORIGIN, 0, (LPARAM)lpPoint);
	}

	UINT GetSelectedCount() const
	{
		ASSERT(::IsWindow(_window));
		return (UINT)::SendMessage(_window, LVM_GETSELECTEDCOUNT, 0, 0L);
	}

	BOOL GetItemRect(int nItem, LPRECT lpRect, UINT nCode) const
	{
		ASSERT(::IsWindow(_window));
		lpRect->left = nCode;
		return (BOOL)::SendMessage(_window, LVM_GETITEMRECT, (WPARAM)nItem, (LPARAM)lpRect);
	}

#ifndef _WIN32_WCE
	HCURSOR GetHotCursor() const
	{
		ASSERT(::IsWindow(_window));
		return (HCURSOR)::SendMessage(_window, LVM_GETHOTCURSOR, 0, 0L);
	}

	HCURSOR SetHotCursor(HCURSOR hHotCursor)
	{
		ASSERT(::IsWindow(_window));
		return (HCURSOR)::SendMessage(_window, LVM_SETHOTCURSOR, 0, (LPARAM)hHotCursor);
	}

	int GetHotItem() const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETHOTITEM, 0, 0L);
	}

	int SetHotItem(int nIndex)
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_SETHOTITEM, nIndex, 0L);
	}
#endif // !_WIN32_WCE

	BOOL GetColumnOrderArray(int nCount, int* lpnArray) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray);
	}

	BOOL SetColumnOrderArray(int nCount, int* lpnArray)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETCOLUMNORDERARRAY, nCount, (LPARAM)lpnArray);
	}

	/*CHeaderCtrl GetHeader() const
	{
		ASSERT(::IsWindow(_window));
		return CHeaderCtrl((HWND)::SendMessage(_window, LVM_GETHEADER, 0, 0L));
	}*/

	BOOL GetSubItemRect(int nItem, int nSubItem, int nFlag, LPRECT lpRect) const
	{
		ASSERT(::IsWindow(_window));
		ASSERT((GetStyle() & LVS_TYPEMASK) == LVS_REPORT);
		ASSERT(lpRect != nullptr);
		lpRect->top = nSubItem;
		lpRect->left = nFlag;
		return (BOOL)::SendMessage(_window, LVM_GETSUBITEMRECT, nItem, (LPARAM)lpRect);
	}

	DWORD SetIconSpacing(int cx, int cy)
	{
		ASSERT(::IsWindow(_window));
		ASSERT((GetStyle() & LVS_TYPEMASK) == LVS_ICON);
		return (DWORD)::SendMessage(_window, LVM_SETICONSPACING, 0, MAKELPARAM(cx, cy));
	}

	int GetISearchString(LPTSTR lpstr) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETISEARCHSTRING, 0, (LPARAM)lpstr);
	}

	void GetItemSpacing(SIZE& sizeSpacing, BOOL bSmallIconView = FALSE) const
	{
		ASSERT(::IsWindow(_window));
		DWORD dwRet = (DWORD)::SendMessage(_window, LVM_GETITEMSPACING, bSmallIconView, 0L);
		sizeSpacing.cx = LOWORD(dwRet);
		sizeSpacing.cy = HIWORD(dwRet);
	}

#if (_WIN32_WCE >= 410)
	void SetItemSpacing(INT cySpacing)
	{
		ASSERT(::IsWindow(_window));
		ListView_SetItemSpacing(_window, cySpacing);
	}
#endif // (_WIN32_WCE >= 410)

	// single-selection only
	int GetSelectedIndex() const
	{
		ASSERT(::IsWindow(_window));
		ASSERT((GetStyle() & LVS_SINGLESEL) != 0);
		return (int)::SendMessage(_window, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
	}

	BOOL GetSelectedItem(LPLVITEM pItem) const
	{
		ASSERT(::IsWindow(_window));
		ASSERT((GetStyle() & LVS_SINGLESEL) != 0);
		ASSERT(pItem != nullptr);
		pItem->iItem = (int)::SendMessage(_window, LVM_GETNEXTITEM, (WPARAM)-1, MAKELPARAM(LVNI_ALL | LVNI_SELECTED, 0));
		if(pItem->iItem == -1)
			return FALSE;
		return (BOOL)::SendMessage(_window, LVM_GETITEM, 0, (LPARAM)pItem);
	}

	// extended list view styles
	DWORD GetExtendedListViewStyle() const
	{
		ASSERT(::IsWindow(_window));
		return (DWORD)::SendMessage(_window, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0L);
	}

	// dwExMask = 0 means all styles
	DWORD SetExtendedListViewStyle(DWORD dwExStyle, DWORD dwExMask = 0)
	{
		ASSERT(::IsWindow(_window));
		return (DWORD)::SendMessage(_window, LVM_SETEXTENDEDLISTVIEWSTYLE, dwExMask, dwExStyle);
	}

	// checkboxes only
	BOOL GetCheckState(int nIndex) const
	{
		ASSERT(::IsWindow(_window));
		ASSERT((GetExtendedListViewStyle() & LVS_EX_CHECKBOXES) != 0);
		UINT uRet = GetItemState(nIndex, LVIS_STATEIMAGEMASK);
		return (uRet >> 12) - 1;
	}

	BOOL SetCheckState(int nItem, BOOL bCheck)
	{
		int nCheck = bCheck ? 2 : 1;   // one based index
		return SetItemState(nItem, INDEXTOSTATEIMAGEMASK(nCheck), LVIS_STATEIMAGEMASK);
	}

	// view type
	DWORD GetViewType() const
	{
		ASSERT(::IsWindow(_window));
		return (GetStyle() & LVS_TYPEMASK);
	}

	DWORD SetViewType(DWORD dwType)
	{
		ASSERT(::IsWindow(_window));
		ASSERT(dwType == LVS_ICON || dwType == LVS_SMALLICON || dwType == LVS_LIST || dwType == LVS_REPORT);
		DWORD dwOldType = GetViewType();
		if(dwType != dwOldType)
			ModifyStyle(LVS_TYPEMASK, (dwType & LVS_TYPEMASK));
		return dwOldType;
	}

#if (_WIN32_IE >= 0x0400)
#ifndef _WIN32_WCE
	BOOL GetBkImage(LPLVBKIMAGE plvbki) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETBKIMAGE, 0, (LPARAM)plvbki);
	}

	BOOL SetBkImage(LPLVBKIMAGE plvbki)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETBKIMAGE, 0, (LPARAM)plvbki);
	}
#endif // !_WIN32_WCE

	int GetSelectionMark() const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETSELECTIONMARK, 0, 0L);
	}

	int SetSelectionMark(int nIndex)
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_SETSELECTIONMARK, 0, nIndex);
	}

#ifndef _WIN32_WCE
	BOOL GetWorkAreas(int nWorkAreas, LPRECT lpRect) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETWORKAREAS, nWorkAreas, (LPARAM)lpRect);
	}

	BOOL SetWorkAreas(int nWorkAreas, LPRECT lpRect)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETWORKAREAS, nWorkAreas, (LPARAM)lpRect);
	}

	DWORD GetHoverTime() const
	{
		ASSERT(::IsWindow(_window));
		ASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0);
		return (DWORD)::SendMessage(_window, LVM_GETHOVERTIME, 0, 0L);
	}

	DWORD SetHoverTime(DWORD dwHoverTime)
	{
		ASSERT(::IsWindow(_window));
		ASSERT((GetExtendedListViewStyle() & (LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE | LVS_EX_TWOCLICKACTIVATE)) != 0);
		return (DWORD)::SendMessage(_window, LVM_SETHOVERTIME, 0, dwHoverTime);
	}

	BOOL GetNumberOfWorkAreas(int* pnWorkAreas) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETNUMBEROFWORKAREAS, 0, (LPARAM)pnWorkAreas);
	}
#endif // !_WIN32_WCE

	BOOL SetItemCountEx(int nItems, DWORD dwFlags)
	{
		ASSERT(::IsWindow(_window));
		ASSERT(((GetStyle() & LVS_OWNERDATA) != 0) && (((GetStyle() & LVS_TYPEMASK) == LVS_REPORT) || ((GetStyle() & LVS_TYPEMASK) == LVS_LIST)));
		return (BOOL)::SendMessage(_window, LVM_SETITEMCOUNT, nItems, dwFlags);
	}

#ifndef _WIN32_WCE
	QToolTip GetToolTips() const
	{
		ASSERT(::IsWindow(_window));
		return QToolTip((HWND)::SendMessage(_window, LVM_GETTOOLTIPS, 0, 0L));
	}

	QToolTip SetToolTips(HWND hWndTT)
	{
		ASSERT(::IsWindow(_window));
		return QToolTip((HWND)::SendMessage(_window, LVM_SETTOOLTIPS, (WPARAM)hWndTT, 0L));
	}

	BOOL GetUnicodeFormat() const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETUNICODEFORMAT, 0, 0L);
	}

	BOOL SetUnicodeFormat(BOOL bUnicode = TRUE)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETUNICODEFORMAT, bUnicode, 0L);
	}
#endif // !_WIN32_WCE
#endif // (_WIN32_IE >= 0x0400)

#if (_WIN32_WINNT >= 0x0501)
	int GetSelectedColumn() const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETSELECTEDCOLUMN, 0, 0L);
	}

	void SetSelectedColumn(int nColumn)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, LVM_SETSELECTEDCOLUMN, nColumn, 0L);
	}

	DWORD GetView() const
	{
		ASSERT(::IsWindow(_window));
		return (DWORD)::SendMessage(_window, LVM_GETVIEW, 0, 0L);
	}

	int SetView(DWORD dwView)
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_SETVIEW, dwView, 0L);
	}

	BOOL IsGroupViewEnabled() const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_ISGROUPVIEWENABLED, 0, 0L);
	}

	int GetGroupInfo(int nGroupID, PLVGROUP pGroup) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETGROUPINFO, nGroupID, (LPARAM)pGroup);
	}

	int SetGroupInfo(int nGroupID, PLVGROUP pGroup)
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_SETGROUPINFO, nGroupID, (LPARAM)pGroup);
	}

	void GetGroupMetrics(PLVGROUPMETRICS pGroupMetrics) const
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, LVM_GETGROUPMETRICS, 0, (LPARAM)pGroupMetrics);
	}

	void SetGroupMetrics(PLVGROUPMETRICS pGroupMetrics)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, LVM_SETGROUPMETRICS, 0, (LPARAM)pGroupMetrics);
	}

	void GetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo) const
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, LVM_GETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo);
	}

	BOOL SetTileViewInfo(PLVTILEVIEWINFO pTileViewInfo)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETTILEVIEWINFO, 0, (LPARAM)pTileViewInfo);
	}

	void GetTileInfo(PLVTILEINFO pTileInfo) const
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, LVM_GETTILEINFO, 0, (LPARAM)pTileInfo);
	}

	BOOL SetTileInfo(PLVTILEINFO pTileInfo)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETTILEINFO, 0, (LPARAM)pTileInfo);
	}

	BOOL GetInsertMark(LPLVINSERTMARK pInsertMark) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETINSERTMARK, 0, (LPARAM)pInsertMark);
	}

	BOOL SetInsertMark(LPLVINSERTMARK pInsertMark)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETINSERTMARK, 0, (LPARAM)pInsertMark);
	}

	int GetInsertMarkRect(LPRECT lpRect) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETINSERTMARKRECT, 0, (LPARAM)lpRect);
	}

	COLORREF GetInsertMarkColor() const
	{
		ASSERT(::IsWindow(_window));
		return (COLORREF)::SendMessage(_window, LVM_GETINSERTMARKCOLOR, 0, 0L);
	}

	COLORREF SetInsertMarkColor(COLORREF clr)
	{
		ASSERT(::IsWindow(_window));
		return (COLORREF)::SendMessage(_window, LVM_SETINSERTMARKCOLOR, 0, clr);
	}

	COLORREF GetOutlineColor() const
	{
		ASSERT(::IsWindow(_window));
		return (COLORREF)::SendMessage(_window, LVM_GETOUTLINECOLOR, 0, 0L);
	}

	COLORREF SetOutlineColor(COLORREF clr)
	{
		ASSERT(::IsWindow(_window));
		return (COLORREF)::SendMessage(_window, LVM_SETOUTLINECOLOR, 0, clr);
	}
#endif // (_WIN32_WINNT >= 0x0501)

#if (_WIN32_WINNT >= 0x0600)
	int GetGroupCount() const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETGROUPCOUNT, 0, 0L);
	}

	BOOL GetGroupInfoByIndex(int nIndex, PLVGROUP pGroup) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETGROUPINFOBYINDEX, nIndex, (LPARAM)pGroup);
	}

	BOOL GetGroupRect(int nGroupID, int nType, LPRECT lpRect) const
	{
		ASSERT(::IsWindow(_window));
		ASSERT(lpRect != nullptr);
		if(lpRect != nullptr)
			lpRect->top = nType;
		return (BOOL)::SendMessage(_window, LVM_GETGROUPRECT, nGroupID, (LPARAM)lpRect);
	}

	UINT GetGroupState(int nGroupID, UINT uMask) const
	{
		ASSERT(::IsWindow(_window));
		return (UINT)::SendMessage(_window, LVM_GETGROUPSTATE, nGroupID, (LPARAM)uMask);
	}

	int GetFocusedGroup() const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETFOCUSEDGROUP, 0, 0L);
	}

	BOOL GetEmptyText(LPWSTR lpstrText, int cchText) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETEMPTYTEXT, cchText, (LPARAM)lpstrText);
	}

	BOOL GetFooterRect(LPRECT lpRect) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETFOOTERRECT, 0, (LPARAM)lpRect);
	}

	BOOL GetFooterInfo(LPLVFOOTERINFO lpFooterInfo) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETFOOTERINFO, 0, (LPARAM)lpFooterInfo);
	}

	BOOL GetFooterItemRect(int nItem, LPRECT lpRect) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETFOOTERITEMRECT, nItem, (LPARAM)lpRect);
	}

	BOOL GetFooterItem(int nItem, LPLVFOOTERITEM lpFooterItem) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETFOOTERITEM, nItem, (LPARAM)lpFooterItem);
	}

	BOOL GetItemIndexRect(PLVITEMINDEX pItemIndex, int nSubItem, int nType, LPRECT lpRect) const
	{
		ASSERT(::IsWindow(_window));
		ASSERT(pItemIndex != nullptr);
		ASSERT(lpRect != nullptr);
		if(lpRect != nullptr)
		{
			lpRect->top = nSubItem;
			lpRect->left = nType;
		}
		return (BOOL)::SendMessage(_window, LVM_GETITEMINDEXRECT, (WPARAM)pItemIndex, (LPARAM)lpRect);
	}

	BOOL SetItemIndexState(PLVITEMINDEX pItemIndex, UINT uState, UINT dwMask)
	{
		ASSERT(::IsWindow(_window));
		LVITEM lvi = { 0 };
		lvi.state = uState;
		lvi.stateMask = dwMask;
		return (BOOL)::SendMessage(_window, LVM_SETITEMINDEXSTATE, (WPARAM)pItemIndex, (LPARAM)&lvi);
	}

	BOOL GetNextItemIndex(PLVITEMINDEX pItemIndex, WORD wFlags) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_GETNEXTITEMINDEX, (WPARAM)pItemIndex, MAKELPARAM(wFlags, 0));
	}
#endif // (_WIN32_WINNT >= 0x0600)

// Operations
	int InsertColumn(int nCol, const LVCOLUMN* pColumn)
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_INSERTCOLUMN, nCol, (LPARAM)pColumn);
	}

	int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, 
			int nWidth = -1, int nSubItem = -1, int iImage = -1, int iOrder = -1)
	{
		LVCOLUMN column = { 0 };
		column.mask = LVCF_TEXT|LVCF_FMT;
		column.pszText = (LPTSTR)lpszColumnHeading;
		column.fmt = nFormat;
		if (nWidth != -1)
		{
			column.mask |= LVCF_WIDTH;
			column.cx = nWidth;
		}
		if (nSubItem != -1)
		{
			column.mask |= LVCF_SUBITEM;
			column.iSubItem = nSubItem;
		}
		if (iImage != -1)
		{
			column.mask |= LVCF_IMAGE;
			column.iImage = iImage;
		}
		if (iOrder != -1)
		{
			column.mask |= LVCF_ORDER;
			column.iOrder = iOrder;
		}
		return InsertColumn(nCol, &column);
	}

	BOOL DeleteColumn(int nCol)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_DELETECOLUMN, nCol, 0L);
	}

	int InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam)
	{
		ASSERT(::IsWindow(_window));
		LVITEM item = { 0 };
		item.mask = nMask;
		item.iItem = nItem;
		item.iSubItem = 0;
		item.pszText = (LPTSTR)lpszItem;
		item.state = nState;
		item.stateMask = nStateMask;
		item.iImage = nImage;
		item.lParam = lParam;
		return InsertItem(&item);
	}

	int InsertItem(const LVITEM* pItem)
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_INSERTITEM, 0, (LPARAM)pItem);
	}

	int InsertItem(int nItem, LPCTSTR lpszItem)
	{
		ASSERT(::IsWindow(_window));
		return InsertItem(LVIF_TEXT, nItem, lpszItem, 0, 0, 0, 0);
	}

	int InsertItem(int nItem, LPCTSTR lpszItem, int nImage)
	{
		ASSERT(::IsWindow(_window));
		return InsertItem(LVIF_TEXT|LVIF_IMAGE, nItem, lpszItem, 0, 0, nImage, 0);
	}

	int GetNextItem(int nItem, int nFlags) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_GETNEXTITEM, nItem, MAKELPARAM(nFlags, 0));
	}

	BOOL DeleteItem(int nItem)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_DELETEITEM, nItem, 0L);
	}

	BOOL DeleteAllItems()
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_DELETEALLITEMS, 0, 0L);
	}

	int FindItem(LVFINDINFO* pFindInfo, int nStart) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_FINDITEM, nStart, (LPARAM)pFindInfo);
	}

	int HitTest(LVHITTESTINFO* pHitTestInfo) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_HITTEST, 0, (LPARAM)pHitTestInfo);
	}

	int HitTest(POINT pt, UINT* pFlags) const
	{
		ASSERT(::IsWindow(_window));
		LVHITTESTINFO hti = { 0 };
		hti.pt = pt;
		int nRes = (int)::SendMessage(_window, LVM_HITTEST, 0, (LPARAM)&hti);
		if (pFlags != nullptr)
			*pFlags = hti.flags;
		return nRes;
	}

	BOOL EnsureVisible(int nItem, BOOL bPartialOK)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_ENSUREVISIBLE, nItem, MAKELPARAM(bPartialOK, 0));
	}

	BOOL Scroll(SIZE size)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SCROLL, size.cx, size.cy);
	}

	BOOL RedrawItems(int nFirst, int nLast)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_REDRAWITEMS, nFirst, nLast);
	}

	BOOL Arrange(UINT nCode)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_ARRANGE, nCode, 0L);
	}

	QEdit EditLabel(int nItem)
	{
		ASSERT(::IsWindow(_window));
		return QEdit((HWND)::SendMessage(_window, LVM_EDITLABEL, nItem, 0L));
	}

	BOOL Update(int nItem)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_UPDATE, nItem, 0L);
	}

	BOOL SortItems(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SORTITEMS, (WPARAM)lParamSort, (LPARAM)pfnCompare);
	}

	QImageList RemoveImageList(int nImageList)
	{
		ASSERT(::IsWindow(_window));
		return QImageList((HIMAGELIST)::SendMessage(_window, LVM_SETIMAGELIST, (WPARAM)nImageList, 0));
	}

	QImageList CreateDragImage(int nItem, LPPOINT lpPoint)
	{
		ASSERT(::IsWindow(_window));
		return QImageList((HIMAGELIST)::SendMessage(_window, LVM_CREATEDRAGIMAGE, nItem, (LPARAM)lpPoint));
	}

	DWORD ApproximateViewRect(int cx = -1, int cy = -1, int nCount = -1)
	{
		ASSERT(::IsWindow(_window));
		return (DWORD)::SendMessage(_window, LVM_APPROXIMATEVIEWRECT, nCount, MAKELPARAM(cx, cy));
	}

	int SubItemHitTest(LPLVHITTESTINFO lpInfo) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_SUBITEMHITTEST, 0, (LPARAM)lpInfo);
	}

	int AddColumn(LPCTSTR strItem, int nItem, int nSubItem = -1,
			int nMask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM,
			int nFmt = LVCFMT_LEFT)
	{
		const int cxOffset = 15;
		ASSERT(::IsWindow(_window));
		LVCOLUMN lvc = { 0 };
		lvc.mask = nMask;
		lvc.fmt = nFmt;
		lvc.pszText = (LPTSTR)strItem;
		lvc.cx = GetStringWidth(lvc.pszText) + cxOffset;
		if(nMask & LVCF_SUBITEM)
			lvc.iSubItem = (nSubItem != -1) ? nSubItem : nItem;
		return InsertColumn(nItem, &lvc);
	}

	int AddItem(LPCTSTR strItem, int nImageIndex = -1)
	{
		int it = GetItemCount();

		return AddItem(  it, 0,   strItem, nImageIndex  );
	}

	int AddItem(int nItem, int nSubItem, LPCTSTR strItem, int nImageIndex = -1)
	{
		ASSERT(::IsWindow(_window));
		LVITEM lvItem = {LVIF_TEXT, nItem, nSubItem, 0 };
		lvItem.pszText = (LPTSTR)strItem;

		if(nImageIndex != -1)
		{
			lvItem.mask |= LVIF_IMAGE;
			lvItem.iImage = nImageIndex;
		}
		if(nSubItem == 0)
			return InsertItem(&lvItem);
		return SetItem(&lvItem) ? nItem : -1;
	}

#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
	BOOL SortItemsEx(PFNLVCOMPARE pfnCompare, LPARAM lParamSort)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SORTITEMSEX, (WPARAM)lParamSort, (LPARAM)pfnCompare);
	}
#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)

#if (_WIN32_WINNT >= 0x0501)
	int InsertGroup(int nItem, PLVGROUP pGroup)
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_INSERTGROUP, nItem, (LPARAM)pGroup);
	}

	int AddGroup(PLVGROUP pGroup)
	{
		return InsertGroup(-1, pGroup);
	}

	int RemoveGroup(int nGroupID)
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_REMOVEGROUP, nGroupID, 0L);
	}

	void MoveGroup(int nGroupID, int nItem)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, LVM_MOVEGROUP, nGroupID, nItem);
	}

	void MoveItemToGroup(int nItem, int nGroupID)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, LVM_MOVEITEMTOGROUP, nItem, nGroupID);
	}

	int EnableGroupView(BOOL bEnable)
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_ENABLEGROUPVIEW, bEnable, 0L);
	}

	int SortGroups(PFNLVGROUPCOMPARE pCompareFunc, LPVOID lpVoid = nullptr)
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_SORTGROUPS, (WPARAM)pCompareFunc, (LPARAM)lpVoid);
	}

	void InsertGroupSorted(PLVINSERTGROUPSORTED pInsertGroupSorted)
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, LVM_INSERTGROUPSORTED, (WPARAM)pInsertGroupSorted, 0L);
	}

	void RemoveAllGroups()
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, LVM_REMOVEALLGROUPS, 0, 0L);
	}

	BOOL HasGroup(int nGroupID)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_HASGROUP, nGroupID, 0L);
	}

	BOOL InsertMarkHitTest(LPPOINT lpPoint, LPLVINSERTMARK pInsertMark) const
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_INSERTMARKHITTEST, (WPARAM)lpPoint, (LPARAM)pInsertMark);
	}

	BOOL SetInfoTip(PLVSETINFOTIP pSetInfoTip)
	{
		ASSERT(::IsWindow(_window));
		return (BOOL)::SendMessage(_window, LVM_SETINFOTIP, 0, (LPARAM)pSetInfoTip);
	}

	void CancelEditLabel()
	{
		ASSERT(::IsWindow(_window));
		::SendMessage(_window, LVM_CANCELEDITLABEL, 0, 0L);
	}

	UINT MapIndexToID(int nIndex) const
	{
		ASSERT(::IsWindow(_window));
		return (UINT)::SendMessage(_window, LVM_MAPINDEXTOID, nIndex, 0L);
	}

	int MapIDToIndex(UINT uID) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_MAPIDTOINDEX, uID, 0L);
	}
#endif // (_WIN32_WINNT >= 0x0501)

#if (_WIN32_WINNT >= 0x0600)
	int HitTestEx(LPLVHITTESTINFO lpHitTestInfo) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_HITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo);
	}

	int HitTestEx(POINT pt, UINT* pFlags) const
	{
		ASSERT(::IsWindow(_window));
		LVHITTESTINFO hti = { 0 };
		hti.pt = pt;
		int nRes = (int)::SendMessage(_window, LVM_HITTEST, (WPARAM)-1, (LPARAM)&hti);
		if (pFlags != nullptr)
			*pFlags = hti.flags;
		return nRes;
	}

	int SubItemHitTestEx(LPLVHITTESTINFO lpHitTestInfo) const
	{
		ASSERT(::IsWindow(_window));
		return (int)::SendMessage(_window, LVM_SUBITEMHITTEST, (WPARAM)-1, (LPARAM)lpHitTestInfo);
	}
#endif // (_WIN32_WINNT >= 0x0600)

	// single-selection only
	BOOL SelectItem(int nIndex)
	{
		ASSERT(::IsWindow(_window));
		ASSERT((GetStyle() & LVS_SINGLESEL) != 0);

		BOOL bRet = SetItemState(nIndex, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
		if(bRet)
			bRet = EnsureVisible(nIndex, FALSE);
		return bRet;
	}
};
 

}
 
}//micro